/**
  ******************************************************************************
  * @file    uart.c 
  * @author  casy
  * @version V1.0
  * @Board   stm32f103rbt6
  * @date    2014/07/02
  * @brief   
  ******************************************************************************
**/ 
/*******************************************************************************
stm32f103rbt6(LQFP64):
stm32f103c8t6(LQFP48):

PIN42--PA9--USART1_TX
PIN43--PA10--USART1_RX
	
PIN29--PB10--USART3_TX
PIN30--PB11--USART3_RX

PIN16--PA2--USART2_TX
PIN17--PA3--USART2_RX

  *  知识点：
  *  RXEN = 1：移位寄存器中的内容已经转移到RDR
  *  RXNEIE =1:产生中断
  *	 
	串口使用DMA进行发送，可以通过设置USART_CR3寄存器上的DMAT位激活。只要TXE位被置
起，就从配置成使用DMA外设的SRAM区装载数据到USART_DR寄存器。为USART的发送分
配一个DMA通道的步骤如下(x表示通道号)： 
1.  在DMA控制寄存器上将USART_DR寄存器地址配置成DMA传输的目的地址。在每个TXE事
件后，数据将被传送到这个地址。 
2.  在DMA控制寄存器上将存储器地址配置成DMA传输的源地址。在每个TXE事件后，数据将
从此存储器区传送到USART_DR寄存器。 
3.  在DMA控制寄存器中配置要传输的总的字节数。 
4.  在DMA寄存器上配置通道优先级。 
5.  根据应用程序的要求配置在传输完成一半还是全部完成时产生DMA中断。 
6.  在DMA寄存器上激活该通道。 
7.  当DMA控制器中指定的数据量传输完成时，DMA控制器在该DMA通道的中断向量上产生一
中断。在中断服务程序里，软件应将USART_CR3寄存器的DMA位清零。 
注意：  如果DMA被用于发送，不要使能TXEIE位。 

	串口使用DMA进行接收，可以通过设置USART_CR3寄存器的DMAR位激活。只要接收到一个字
节，数据就从USART_DR寄存器放到配置成使用DMA的SRAM区(参考DMA技术说明)。为USART的接
收分配一个DMA通道步骤如下(x表示通道号)： 
1.  通过DMA控制寄存器把USART_DR寄存器地址配置成传输的源地址。在每个RXNE事件后
    此地址上的数据将传输到存储器。 
2.  通过DMA控制寄存器把存储器地址配置成传输的目的地址。在每个RXNE事件后，数据将从
    USART_DR传输到此存储器区。 
3.  在DMA控制寄存器中配置要传输的总的字节数。 
4.  在DMA寄存器上配置通道优先级。。 
5.  根据应用程序的要求配置在传输完成一半还是全部完成时产生DMA中断。 
6.  在DMA控制寄存器上激活该通道。通用同步异步收发器(USART)  
7.  当DMA控制器中指定的传输数据量接收完成时，DMA控制器在该DMA通道的中断矢量上产生
	一中断。在中断程序里， USART_CR3寄存器的DMAR位应该被软件清零。 
注意：  如果DMA被用来接收，不要使能RXNEIE位。
 
         
********************************************************************************/


#include "uart.h"


/*******************************************************************************
* Function Name  : USART1_Init
* Description    : 
* Input          : baudrate
* Output         : None
* Return         : None
*******************************************************************************/
void USART1_Init(u32 baudrate)
{
  GPIO_InitTypeDef   GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef  NVIC_InitStructure;
  //USART1，GPIOA~E挂在APB2总线上
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA| RCC_APB2Periph_AFIO, ENABLE);	
  
  /*A9 USART1.TX 推挽输出*/ 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  /*A10 USART1.RX 浮空输入 */ 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	
  GPIO_Init(GPIOA, &GPIO_InitStructure);
        
  /*配置USART1的工作模式*/
  USART_InitStructure.USART_BaudRate =baudrate;               //波特率      
  USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长8bit										
  USART_InitStructure.USART_StopBits = USART_StopBits_1;	    //停止位1位									
  USART_InitStructure.USART_Parity = USART_Parity_No;         //无奇偶校验							
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发使能
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流控制							    
  USART_Init(USART1, &USART_InitStructure);                       //初始化外设 USARTx	  

  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;		
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			
  NVIC_Init(&NVIC_InitStructure); //必须初始化NVIC，才能使串口中断接收正常工作	 
  
  USART_Cmd(USART1, ENABLE);		       //使能USART1外设
  
  USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //使能接收中断
 // USART_ITConfig(USART1, USART_IT_TXE,ENABLE); //使能发送中断
  
  USART_ClearFlag(USART1, USART_FLAG_TC);  
  
}

/*******************************************************************************
* Function Name  : USART2_Init
* Description    : 
* Input          : baudrate
* Output         : None
* Return         : None
*******************************************************************************/
void USART2_Init(u32 baudrate)
{
  GPIO_InitTypeDef   GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef  NVIC_InitStructure;
  //USART1，GPIOA~E挂在APB2总线上
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);	 
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
  
 // GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);  // very important
  
  /*PA2 USART2.TX复用推挽输出*/ 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  /*PA3 USART2.RX浮空输入 */ 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	
  GPIO_Init(GPIOA, &GPIO_InitStructure);
     
  /*配置USART2的工作模式*/
  USART_InitStructure.USART_BaudRate =baudrate;               //波特率      
  USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长8bit										
  USART_InitStructure.USART_StopBits = USART_StopBits_1;	    //停止位1位									
  USART_InitStructure.USART_Parity = USART_Parity_No;         //无奇偶校验							
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发使能
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//无硬件流控制							    
  USART_Init(USART2, &USART_InitStructure);                       //初始化外设 USARTx	  

  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
  NVIC_Init(&NVIC_InitStructure); //必须初始化NVIC，才能使串口中断接收正常工作	 
 
  USART_Cmd(USART2, ENABLE);		       //使能USART1外设
  USART_ITConfig(USART2,USART_IT_RXNE,ENABLE); //使能接收中断
 // USART_ITConfig(USART2, USART_IT_TXE,ENABLE); //使能发送中断
  USART_ClearFlag(USART2, USART_FLAG_TC);  
  
}

/*******************************************************************************
* Function Name  : USART3_Init
* Description    : 
* Input          : baudrate
* Output         : None
* Return         : None
*******************************************************************************/
void USART3_Init(u32 baudrate)
{
  GPIO_InitTypeDef   GPIO_InitStructure;
  USART_InitTypeDef  USART_InitStructure;
  NVIC_InitTypeDef   NVIC_InitStructure;
  
  //USART1，GPIOA~E挂在APB2总线上
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);	
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
  
  /*PB10 USART3.TX推挽输出*/ 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  /*PB11 USART3.RX浮空输入 */ 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	
  GPIO_Init(GPIOB, &GPIO_InitStructure);
    
  /*配置USART3的工作模式*/
  USART_InitStructure.USART_BaudRate =baudrate;               //波特率      
  USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长8bit										
  USART_InitStructure.USART_StopBits = USART_StopBits_1;	    //停止位1位									
  USART_InitStructure.USART_Parity = USART_Parity_No;         //无奇偶校验							
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发使能
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//无硬件流控制							    
  USART_Init(USART3, &USART_InitStructure);                       //初始化外设 USARTx	  

  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;		
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
  NVIC_Init(&NVIC_InitStructure); //必须初始化NVIC，才能使串口中断接收正常工作	 
 
  USART_Cmd(USART3, ENABLE);		       //使能USART1外设
  USART_ITConfig(USART3,USART_IT_RXNE,ENABLE); //使能接收中断
 // USART_ITConfig(USART3, USART_IT_TXE,ENABLE); //使能发送中断
  USART_ClearFlag(USART3, USART_FLAG_TC);  
  
}

/*******************************************************************************
* Function Name  : USART_PutChar
* Description    : 串口调试助手请设置为字符显示，16进制显示的ASCII值<128
* Input          : USARTx, c
* Output         : None
* Return         : None
*******************************************************************************/
void USART_PutChar(USART_TypeDef* USARTx, char c)
{
    USART_SendData(USARTx, c);
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
}

/*******************************************************************************
* Function Name  : USART_PutStr
* Description    : 如果是数组0x00 则不能用该函数发送
* Input          : USARTx, str
* Output         : None
* Return         : None
*******************************************************************************/
void USART_PutStr(USART_TypeDef* USARTx, char (*str))
{
    while(*str)
    {
        USART_SendData(USARTx, *str++);
        while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);//等待发送完毕 
    }
}

/*******************************************************************************
* Function Name  : USART_Send_Array
* Description    : 该函数可以发送数组0x00 
* Input          : USARTx, str
* Output         : None
* Return         : None
*******************************************************************************/
void USART_Send_Array(USART_TypeDef* USARTx,u8 * send_array,u8 array_size)  
{
    
   unsigned char i=0;  

	while(i<array_size)   
	{      
		USART_SendData(USARTx,send_array[i++]);        //通过库函数  发送数据
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);//等待发送完毕 
	}
        
}

/**********************************************************************************************
 ** 函数名   : fputc()
 ** 功  能   :重定向C库函数printf到USART:重新定义stdio.h中的fputc()函数，使printf()输出到USART
 ** 输  入   :int ch，FILE *f
 ** 输  出   :int ch
 ** 使用说明 ：
 **          Example:printf("i=%d,ch=%c\n",i,ch);
 			printf("\r\n LCD驱动IC为:%x \r\n",0x55); 
  %d:按10进制有符号整数实际长度输出
	%u:按10进制无符号整数实际长度输出
	%o:按8进制数据实际长度输出
	%x:按16进制数据实际长度输出
	%c:输出一个字符
	%s:输出一个字符串
************************************************************************************************/
#if 1

int fputc(int ch,FILE *f)
{
  USART_SendData(USART1,(u8)ch);	                     //将ch从USART1发送出去
  while (!(USART1->SR & USART_FLAG_TXE));		     //等待发送完毕									  
  return ch;																	         //返回 ch
}	

#else  // swo

int fputc(int c,FILE *stream)
{ 
 return (int)ITM_SendChar((uint32_t)c); 
} 


#endif

/***********************************************************************************************
* Function Name  : int fgetc(FILE *f)
* Description    : Retargets the C library printf function to the USART.fgetc重定向
* Input          : None
* Output         : None
* Return         : 读取到的字符
************************************************************************************************/
int fgetc(FILE *f)
{
/* Loop until received a char */
  while(!(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET))
        {
        }	
/* Read a character from the USART1 and RETURN */
return (USART_ReceiveData(USART1));
}


bool uart_full_flag = false;
 u8  uart1_buff[10];

// AABB20150802185549FF  // sent
//FF AA BB 20 15 08 02 18 55 49  //Received 
void  USART1_IRQHandler(void)
{
  static u8 count;
  
  if(USART_GetFlagStatus(USART1,USART_IT_RXNE)!= RESET) 
  {   
    USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除中断标志
   
     uart1_buff[count++] =  USART_ReceiveData(USART1);
     if(count>= 10)
     {
     count =0;    
     uart_full_flag =true;
     }
  }
}


void USART2_IRQHandler(void)
{
   if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) 
  {
	USART_ClearITPendingBit(USART2, USART_IT_RXNE);

   
  }
  
}


void USART3_IRQHandler(void)
{
   if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) 
  {
	USART_ClearITPendingBit(USART3, USART_IT_RXNE);

   
  }
     
}


